package lab.cadl.lirui.markdown.core.model

import kotlin.math.ceil

interface Visitor {
    fun visit(element: Element)
    fun visit(document: MarkdownDocument)
    fun visit(section: Section)
    fun visit(heading: Heading)
    fun visit(paragraph: Paragraph)
    fun visit(orderedList: OrderedList)
    fun visit(bulletList: BulletList)
    fun visit(listItem: ListItem)
    fun visit(indentCodeBlock: IndentCodeBlock)
    fun visit(fencedCodeBlock: FencedCodeBlock)
    fun visit(keyWordBlock: KeyWordBlock)
    fun visit(imageBlock: ImageBlock)
    fun visit(blockQuote: BlockQuote)
    fun visit(tableBlock: TableBlock)
    fun visit(thematicBreak: ThematicBreak)
    fun visit(hardLineBreak: HardLineBreak)
    fun visit(text: Text)
    fun visit(image: Image)
    fun visit(code: Code)
    fun visit(emphasis: Emphasis)
    fun visit(formula: Formula)
    fun visit(urlLink: UrlLink)
    fun visit(refLink: RefLink)
    fun visit(italyText: ItalyText)
    fun visit(deleteText: DeleteText)
    fun visit(entityText: EntityText)
    fun visit(footnote: Footnote)
    fun visit(algorithmBlock: AlgorithmBlock)
    fun visit(algorithmInput: AlgorithmInput)
    fun visit(algorithmOutput: AlgorithmOutput)
    fun visit(algorithmLine: AlgorithmLine)
    fun visit(formulaBlock: FormulaBlock)
    fun visit(abstractSection: AbstractSection)
    fun visit(refSection: RefSection)
    fun visit(paperRef: PaperRef)
    fun visit(tocBlock: TocBlock)
}

abstract class AbstractVisitor : Visitor {
    override fun visit(element: Element) {
        NotImplementedError("not implemented for $element")
    }

    override fun visit(document: MarkdownDocument) {
        visitChildren(document)
    }

    override fun visit(section: Section) {
        visitChildren(section)
    }

    override fun visit(heading: Heading) {
        visitChildren(heading)
    }

    override fun visit(paragraph: Paragraph) {
        visitChildren(paragraph)
    }

    override fun visit(orderedList: OrderedList) {
        visitChildren(orderedList)
    }

    override fun visit(bulletList: BulletList) {
        visitChildren(bulletList)
    }

    override fun visit(listItem: ListItem) {
        visitChildren(listItem)
    }

    override fun visit(indentCodeBlock: IndentCodeBlock) {
        visitChildren(indentCodeBlock)
    }

    override fun visit(fencedCodeBlock: FencedCodeBlock) {
        visitChildren(fencedCodeBlock)
    }

    override fun visit(imageBlock: ImageBlock) {
        visitChildren(imageBlock)
    }

    override fun visit(blockQuote: BlockQuote) {
        visitChildren(blockQuote)
    }

    override fun visit(thematicBreak: ThematicBreak) {
        visitChildren(thematicBreak)
    }

    override fun visit(hardLineBreak: HardLineBreak) {
        visitChildren(hardLineBreak)
    }

    override fun visit(tableBlock: TableBlock) {
        visitChildren(tableBlock)
    }

    override fun visit(text: Text) {
        visitChildren(text)
    }

    override fun visit(image: Image) {
        visitChildren(image)
    }

    override fun visit(code: Code) {
        visitChildren(code)
    }

    override fun visit(emphasis: Emphasis) {
        visitChildren(emphasis)
    }

    override fun visit(formula: Formula) {
        visitChildren(formula)
    }

    override fun visit(urlLink: UrlLink) {
        visitChildren(urlLink)
    }

    override fun visit(refLink: RefLink) {
        visitChildren(refLink)
    }

    override fun visit(deleteText: DeleteText) {
        visitChildren(deleteText)
    }

    override fun visit(italyText: ItalyText) {
        visitChildren(italyText)
    }

    override fun visit(entityText: EntityText) {
        visitChildren(entityText)
    }

    override fun visit(footnote: Footnote) {
        visitChildren(footnote)
    }

    override fun visit(algorithmBlock: AlgorithmBlock) {
        visitChildren(algorithmBlock)
    }

    override fun visit(algorithmInput: AlgorithmInput) {
        visitChildren(algorithmInput)
    }

    override fun visit(algorithmOutput: AlgorithmOutput) {
        visitChildren(algorithmOutput)
    }

    override fun visit(algorithmLine: AlgorithmLine) {
        visitChildren(algorithmLine)
    }

    override fun visit(formulaBlock: FormulaBlock) {
        visitChildren(formulaBlock)
    }

    override fun visit(abstractSection: AbstractSection) {
        visitChildren(abstractSection)
    }

    override fun visit(paperRef: PaperRef) {
        visitChildren(paperRef)
    }

    override fun visit(refSection: RefSection) {
        visitChildren(refSection)
    }

    override fun visit(keyWordBlock: KeyWordBlock) {
        visitChildren(keyWordBlock)
    }

    override fun visit(tocBlock: TocBlock) {
        visitChildren(tocBlock)
    }

    protected fun visitChildren(parent: Element) {
        parent.children.forEach {
            it.accept(this)
        }
    }
}


